﻿

namespace HDJ.Framework.Core.FixedPointy
{
   public struct FixVector3
    {
        public static readonly FixVector3 Zero = new FixVector3(Fix64.Zero, Fix64.Zero, Fix64.Zero);
        public static readonly FixVector3 One = new FixVector3(Fix64.One, Fix64.One, Fix64.One);
        public static readonly FixVector3 UnitX = new FixVector3(Fix64.One, Fix64.Zero, Fix64.Zero);
        public static readonly FixVector3 UnitY = new FixVector3(Fix64.Zero, Fix64.One, Fix64.Zero);
        public static readonly FixVector3 UnitZ = new FixVector3(Fix64.Zero, Fix64.Zero, Fix64.One);

      public  Fix64 x, y, z;

        public FixVector3(Fix64 x, Fix64 y, Fix64 z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }
        public FixVector3(long x, long y, long z)
        {
            this.x = (Fix64)x;
            this.y = (Fix64)y;
            this.z = (Fix64)z;
        }
        public FixVector3(int x, int y, int z)
        {
            this.x = new Fix64(x);
            this.y = new Fix64(y);
            this.z = new Fix64(z);
        }
        public FixVector3(float x, float y, float z)
        {
            this.x = new Fix64(x);
            this.y = new Fix64(y);
            this.z = new Fix64(z);
        }
        public FixVector3(double x, double y, double z)
        {
            this.x = new Fix64(x);
            this.y = new Fix64(y);
            this.z = new Fix64(z);
        }
        public FixVector3(decimal x, decimal y, decimal z)
        {
            this.x = new Fix64(x);
            this.y = new Fix64(y);
            this.z = new Fix64(z);
        }



        #region 运算
        public static implicit operator FixVector3(FixVector2 value)
        {
            return new FixVector3(value.x, value.y, Fix64.Zero);
        }

        public static FixVector3 operator +(FixVector3 rhs)
        {
            return rhs;
        }
        public static FixVector3 operator -(FixVector3 rhs)
        {
            return new FixVector3(-rhs.x, -rhs.y, -rhs.z);
        }

        public static FixVector3 operator +(FixVector3 lhs, FixVector3 rhs)
        {
            return new FixVector3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z);
        }
        public static FixVector3 operator -(FixVector3 lhs, FixVector3 rhs)
        {
            return new FixVector3(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z);
        }

        public static FixVector3 operator +(FixVector3 lhs, Fix64 rhs)
        {
            return lhs.ScalarAdd(rhs);
        }
        public static FixVector3 operator +(Fix64 lhs, FixVector3 rhs)
        {
            return rhs.ScalarAdd(lhs);
        }
        public static FixVector3 operator -(FixVector3 lhs, Fix64 rhs)
        {
            return new FixVector3(lhs.x - rhs, lhs.y - rhs, lhs.z - rhs);
        }
        public static FixVector3 operator *(FixVector3 lhs, Fix64 rhs)
        {
            return lhs.ScalarMultiply(rhs);
        }
        public static FixVector3 operator *(Fix64 lhs, FixVector3 rhs)
        {
            return rhs.ScalarMultiply(lhs);
        }
        public static FixVector3 operator /(FixVector3 lhs, Fix64 rhs)
        {
            return new FixVector3(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs);
        }

       

        public Fix64 Dot(FixVector3 rhs)
        {
            return x * rhs.x + y * rhs.y + z * rhs.z;
        }

        public FixVector3 Cross(FixVector3 rhs)
        {
            return new FixVector3(
                y * rhs.z - z * rhs.y,
                z * rhs.x - x * rhs.z,
                x * rhs.y - y * rhs.x
            );
        }

        FixVector3 ScalarAdd(Fix64 value)
        {
            return new FixVector3(x + value, y + value, z + value);
        }
        FixVector3 ScalarMultiply(Fix64 value)
        {
            return new FixVector3(x * value, y * value, z * value);
        }

        public Fix64 Magnitude()
        {
            Fix64 N = x * x + y * y + z*z;
            if (N == Fix64.Zero)
                return Fix64.Zero;

            return Fix64.Sqrt(N);
        }

        public FixVector3 Normalize()
        {
            if (x == Fix64.Zero && y == Fix64.Zero && z == Fix64.Zero)
                return FixVector3.Zero;

            var m = Magnitude();
            return new FixVector3(x / m, y / m, z / m);
        }
        #endregion
        public override string ToString()
        {
            return string.Format("({0}, {1}, {2})", x, y, z);
        }
        public  string ToDoubleString()
        {
            return string.Format("({0}, {1}, {2})", (double)x, (double)y, (double)z);
        }
        public  string ToRawString()
        {
            return string.Format("({0}, {1}, {2})", x.Raw, y.Raw, z.Raw);
        }
    }
}
